﻿#region

#endregion

namespace MediaSage.Lib.Plugin.TMDBProvider
{
    #region

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Reflection;
    using MediaSage.Lib.Configuration;
    using MediaSage.Lib.Database;
    using MediaSage.Lib.Utilities;
    using WatTmdb.V3;

    #endregion

    public class TMDBProvider : PluginBase
    {
        #region Fields

        private Tmdb TMDB_API;
        private string baseImageURL;
        private string language;

        #endregion Fields

        #region Constructors

        public TMDBProvider(Config Configuration, PluginEntity PE)
            : base(Configuration, PE)
        {
            CreateTMDBAPI();
            logger.Log("TMDBProvider Initialized");
        }

        #endregion Constructors

        private void CreateTMDBAPI()
        {
            var ciH = new ConfigItemsHelper(config);
            PluginConfigurationItemEntity piCE = ciH.GetCIByNameForPlugin(base.pluginEntity.ID, "Language");
            if (piCE != null && piCE.Value != null && piCE.Value.Length > 0)
            {
                TMDB_API = new Tmdb("6ed2aa34f177f0ead9943df1bbb3d88d", piCE.Value);
                language = piCE.Value;
            }
            else
            {
                TMDB_API = new Tmdb("6ed2aa34f177f0ead9943df1bbb3d88d");
                language = "en";
            }
            UpdateConfiguration();
        }

        #region Methods

        /// <summary>
        /// </summary>
        /// <param name="name"> </param>
        /// <returns> </returns>
        public override IList<PersonEntity> SearchPersonByName(string name)
        {
            logger.Log(String.Format("Entering TMDBProvider::SearchPersonByName({0})", name));
            IList<PersonEntity> returnValue = new List<PersonEntity>();

            int page = 1;
            TmdbPersonSearch results = TMDB_API.SearchPerson(name, page);
            while (results != null && results.results.Count != 0)
            {
                foreach (PersonResult pr in results.results)
                {
                    PersonEntity pe = new PersonEntity();
                    pe.Name = pr.name;
                    pe.TMDBID = pr.id;
                    returnValue.Add(pe);
                }
                page++;
            }

            logger.Log(String.Format("Exiting TMDBProvider::SearchPersonByName{0}), with {1} names", name,
                                     returnValue.Count));
            return (returnValue);
        }

        private void UpdateConfiguration()
        {
            TmdbConfiguration tmdbConfig = TMDB_API.GetConfiguration();
            baseImageURL = tmdbConfig.images.base_url;
        }

        /// <summary>
        ///     Not applicable for a metadata provider
        /// </summary>
        /// <param name="mediaObject"> </param>
        /// <returns> </returns>
        public override bool Run(MediaClass mediaObject)
        {
            throw new NotImplementedException();
        }

        public override string[] About()
        {
            VersionInfo verInfo = GetVersionInfo();

            string[] returnValue =
                {
                    "TMDBProvider v" + verInfo.MajorVersion + "." + verInfo.MinorVersion + "." +
                    verInfo.BuildNumber
                };
            return returnValue;
        }

        public override IList<MediaFileTypesEntity> ExtensionsHandled()
        {
            return base.pluginEntity.ExtensionsHandled;
        }

        public override PluginEntity GetConfiguration()
        {
            return base.pluginEntity;
        }

        /// <summary>
        ///     Does a full download of media assuming we have an TMDB ID available, if we have an IMDB ID available, it attempts to find it that way
        /// </summary>
        /// <param name="inputMedia"> </param>
        /// <param name="mergeType"> </param>
        /// <returns> </returns>
        public override MediaClass GetMedia(MediaClass inputMedia, MediaMergeType mergeType)
        {
            logger.Log(String.Format("Entering TMDBProvider::GetMedia(inputMedia,{0})", mergeType.ToString()));
            if (inputMedia.TmdbID > 0)
            {
                MediaClass mc = GetMediaByID(inputMedia.TmdbID);
                MediaClass retVal = MediaUtil.MergeMediaObjects(config, inputMedia, mc, mergeType);
                logger.Log(String.Format("Exiting TMDBProvider::GetMedia(inputMedia,{0})", mergeType.ToString()));
                return (retVal);
            }

            if (!String.IsNullOrWhiteSpace(inputMedia.IMDBID))
            {
                // Will try to get the movie via IMDB
                TmdbMovie movie = TMDB_API.GetMovieByIMDB(inputMedia.IMDBID);
                if (movie != null)
                {
                    if (movie.id > 0)
                    {
                        MediaClass mc = GetMediaByID(movie.id);
                        if (mc != null)
                        {
                            MediaClass retVal = MediaUtil.MergeMediaObjects(config, inputMedia, mc, mergeType);
                            logger.Log(String.Format("Exiting TMDBProvider::GetMedia(inputMedia,{0})",
                                                     mergeType.ToString()));
                            return (retVal);
                        }
                    }
                }
            }

            logger.Log("Could not find the inputMedia via TMDB ID or IMDB ID");
            logger.Log(String.Format("Exiting TMDBProvider::GetMedia(inputMedia,{0})", mergeType.ToString()));
            return (inputMedia);
        }

        public override MediaClass GetMediaByID(object ID)
        {
            if (ID == null)
            {
                throw new ArgumentNullException("ID");
            }
            IDictionary<string, ImageEntity> ImagesDownloaded = new Dictionary<string, ImageEntity>();

            if (!(ID is int))
            {
                throw new ArgumentException("TMDBProvider.GetMediaID(ID) must use int for ID");
            }
            var id = (int)ID;
            logger.Log("Entering TMDBProvider.GetMediaByID(" + id + ")");
            var returnValue = new MediaClass(config);
            TmdbMovie MovieInfo = TMDB_API.GetMovieInfo(id);

            returnValue.Adult = MovieInfo.adult;
            returnValue.Budget = MovieInfo.budget.ToString();
            foreach (MovieGenre genre in MovieInfo.genres)
            {
                returnValue.Genre.Add(genre.name);
            }
            returnValue.URL = MovieInfo.homepage;
            returnValue.TmdbID = MovieInfo.id;
            returnValue.IMDBID = MovieInfo.imdb_id;
            returnValue.AltName.Add(MovieInfo.original_title);
            returnValue.Overview = MovieInfo.overview;
            returnValue.Description = MovieInfo.overview;
            returnValue.Popularity = MovieInfo.popularity;
            returnValue.IsMovie = true;

            ImageUpdateManager imageUpdateManager = new ImageUpdateManager(config);

            TmdbMovieReleases ReleaseInfo = TMDB_API.GetMovieReleases(id);
            if (ReleaseInfo != null)
            {
                foreach (ReleaseCountry rc in ReleaseInfo.countries)
                {
                    if (rc.iso_3166_1.ToUpper().Equals("US"))
                    {
                        returnValue.MPAARating = rc.certification;
                    }
                    var ce = new CertificationEntity();
                    ce.CountryCode = rc.iso_3166_1.ToUpper();
                    ce.Certification = rc.certification;
                    returnValue.Certifications.Add(ce);
                }
            }

            foreach (ProductionCompany company in MovieInfo.production_companies)
            {
                if (!returnValue.Studios.Contains(company.name))
                {
                    returnValue.Studios.Add(company.name);
                }
            }
            foreach (ProductionCountry country in MovieInfo.production_countries)
            {
                if (!returnValue.Countries.Contains(country.name))
                {
                    returnValue.Countries.Add(country.name);
                }
            }

            try
            {
                returnValue.Released = DateTime.Parse(MovieInfo.release_date);
            }
            catch (Exception e)
            {
                logger.Log("Failed to parse release date, msg: " + e.Message);
                returnValue.Released = DateTime.MinValue;
            }
            returnValue.Revenue = MovieInfo.revenue.ToString();
            returnValue.RunTime = new TimeSpan(0, MovieInfo.runtime, 0);
            foreach (SpokenLanguage lang in MovieInfo.spoken_languages)
            {
                if (!returnValue.Languages.Contains(lang.name))
                {
                    returnValue.Languages.Add(lang.name);
                }
            }
            returnValue.Subtitle = MovieInfo.tagline;
            returnValue.Title = MovieInfo.title;
            returnValue.Popularity = MovieInfo.vote_average * 10;
            // Ok we got our base stuff.

            TmdbMovieAlternateTitles altTitles = TMDB_API.GetMovieAlternateTitles(id, language);
            foreach (AlternateTitle altTitle in altTitles.titles)
            {
                if (!returnValue.AltName.Contains(altTitle.title))
                {
                    returnValue.AltName.Add(altTitle.title);
                }
            }

            var db = new Database(config);

            var ImageGUIDs = new List<Guid>();

            TmdbMovieCast cast = TMDB_API.GetMovieCast(id);
            foreach (Cast castMember in cast.cast)
            {
                var pe = new PersonEntity();
                pe.Job.Add("Cast");
                TmdbPerson tmdbPerson = TMDB_API.GetPersonInfo(castMember.id);
                pe.Biography = tmdbPerson.biography;
                DateTime time;
                try
                {
                    if (!DateTime.TryParse(tmdbPerson.birthday, out time))
                    {
                        pe.Birthday = null;
                    }
                    else
                    {
                        pe.Birthday = time;
                    }
                }
                catch (Exception)
                {
                    pe.Birthday = null;
                }

                try
                {
                    if (!DateTime.TryParse(tmdbPerson.deathday, out time))
                    {
                        pe.Death = null;
                    }
                    else
                    {
                        pe.Death = time;
                    }
                }
                catch (Exception)
                {
                    pe.Death = null;
                }

                pe.TMDBID = tmdbPerson.id;
                pe.URL = tmdbPerson.profile_path;
                pe.Name = tmdbPerson.name;
                pe.BirthPlace = tmdbPerson.place_of_birth;
                if (base.downloadImages)
                {
                    TmdbPersonImages PersonImages = TMDB_API.GetPersonImages(tmdbPerson.id);
                    int a = 0;
                    foreach (PersonImageProfile PIP in PersonImages.profiles)
                    {
                        if (a < config.MaxImageCount)
                        {
                            try
                            {
                                string URL = baseImageURL + "/original" + PIP.file_path;
                                Image image = null;
                                if (ImagesDownloaded.ContainsKey(URL))
                                {
                                    var ie = new ImageEntity();
                                    ie.ImageSize = EImageSize.poster;
                                    ie.ImageType = EImageType.profile;
                                    ie.Filename = ImagesDownloaded[URL].Filename;
                                    ie.HashCode = ImagesDownloaded[URL].HashCode;
                                    ie.URL = URL;
                                    if (a == 0)
                                    {
                                        pe.Image = ie;
                                    }
                                    else
                                    {
                                        pe.Images.Add(ie);
                                    }
                                }
                                else
                                {
                                    ImageEntity ie = new ImageEntity();
                                    ie.URL = String.Format("{0}/original{1}", baseImageURL, PIP.file_path);
                                    ie.ImageSize = EImageSize.poster;
                                    ie.ImageType = EImageType.profile;
                                    if (a == 0)
                                    {
                                        pe.Image = ie;
                                    }
                                    else
                                    {
                                        pe.Images.Add(ie);
                                    }
                                    imageUpdateManager.GetUpdate(ie);
                                }
                            }
                            catch (Exception E)
                            {
                                logger.Log(Logger.Levels.ERROR, "Error saving retrieving image: " + E.Message);
                            }
                            if (!config.GetAllImages)
                            {
                                a++;
                            }
                        }
                    }
                }
                TmdbPersonCredits PC = TMDB_API.GetPersonCredits(tmdbPerson.id);
                foreach (CastCredit CC in PC.cast)
                {
                    var filmEnt = new FilmographyEntity();
                    var fe = new FilmographyEntity();
                    fe.Character = CC.character;
                    fe.TMDBID = CC.id;
                    fe.Job = "Cast";
                    fe.MovieTitle = CC.original_title;
                    if (base.downloadImages)
                    {
                        try
                        {
                            string URL = baseImageURL + "/original" + CC.poster_path;
                            if (ImagesDownloaded.ContainsKey(URL))
                            {
                                var ie = new ImageEntity();
                                ie.URL = baseImageURL + CC.poster_path;
                                ie.Filename = ImagesDownloaded[URL].Filename;
                                ie.HashCode = ImagesDownloaded[URL].HashCode;
                                ie.ImageSize = EImageSize.poster;
                                ie.ImageType = EImageType.poster;
                                fe.MoviePoster = ie;
                                pe.Images.Add(ie);
                                if (ImageGUIDs.Contains(fe.ID))
                                {
                                    logger.Log("Error");
                                }
                                ImageGUIDs.Add(fe.ID);
                            }
                            else
                            {
                                ImageEntity ie = new ImageEntity
                                                     {
                                                         URL =
                                                             String.Format("{0}/original{1}", baseImageURL,
                                                                           CC.poster_path),
                                                         ImageSize = EImageSize.poster,
                                                         ImageType = EImageType.poster
                                                     };
                                pe.Images.Add(ie);
                                imageUpdateManager.GetUpdate(ie);
                                fe.MoviePoster = ie;
                            }
                        }
                        catch (Exception E)
                        {
                            logger.Log(Logger.Levels.ERROR, "Error saving retrieving image: " + E.Message);
                        }
                    }

                    // Now try to get the IMDB ID of the Movie
                    TmdbMovie adjMovie = TMDB_API.GetMovieInfo(fe.TMDBID);
                    fe.IMDBID = adjMovie.imdb_id;
                }

                returnValue.Cast.Add(pe);
            }

            if (base.downloadImages)
            {
                TmdbMovieImages images = TMDB_API.GetMovieImages(id, language);
                int counter = 0;
                foreach (Backdrop backdrop in images.backdrops)
                {
                    if (counter < config.MaxImageCount)
                    {
                        try
                        {
                            string URL = baseImageURL + "/original" + backdrop.file_path;
                            Image image = null;
                            if (ImagesDownloaded.ContainsKey(URL))
                            {
                                var ie = new ImageEntity();
                                ie.URL = URL;
                                ie.ImageSize = EImageSize.poster;
                                ie.ImageType = EImageType.profile;
                                ie.Filename = ImagesDownloaded[URL].Filename;
                                ie.HashCode = ImagesDownloaded[URL].HashCode;
                                if (counter == 0)
                                {
                                    returnValue.Backdrop = ie;
                                }
                                else
                                {
                                    returnValue.Images.Add(ie);
                                }
                            }
                            else
                            {
                                ImageEntity ie = new ImageEntity();
                                ie.URL = String.Format("{0}/original{1}", baseImageURL, backdrop.file_path);
                                ie.ImageSize = EImageSize.poster;
                                ie.ImageType = EImageType.backdrop;

                                imageUpdateManager.GetUpdate(ie);

                                if (counter == 0)
                                {
                                    returnValue.Backdrop = ie;
                                    counter = 1;
                                }
                                else
                                {
                                    returnValue.Images.Add(ie);
                                }
                            }
                        }
                        catch (Exception E)
                        {
                            logger.Log(Logger.Levels.ERROR, "Error saving retrieving image: " + E.Message);
                        }

                        if (!config.GetAllImages)
                        {
                            counter++;
                        }
                    }
                }

                counter = 0;
                foreach (Poster poster in images.posters)
                {
                    if (counter < config.MaxImageCount)
                    {
                        try
                        {
                            string URL = baseImageURL + "/original" + poster.file_path;
                            Image image = null;
                            if (ImagesDownloaded.ContainsKey(URL))
                            {
                                var ie = new ImageEntity();
                                ie.URL = baseImageURL + poster.file_path;
                                ie.ImageSize = EImageSize.poster;
                                ie.ImageType = EImageType.poster;
                                ie.Filename = ImagesDownloaded[URL].Filename;
                                if (counter == 0)
                                {
                                    returnValue.Poster = ie;
                                }
                                else
                                {
                                    returnValue.Images.Add(ie);
                                }
                            }
                            else
                            {
                                ImageEntity ie = new ImageEntity();
                                ie.URL = String.Format("{0}/original{1}", baseImageURL, poster.file_path);
                                ie.ImageSize = EImageSize.poster;
                                ie.ImageType = EImageType.poster;

                                imageUpdateManager.GetUpdate(ie);

                                if (counter == 0)
                                {
                                    returnValue.Poster = ie;
                                    counter = 1;
                                }
                                else
                                {
                                    returnValue.Images.Add(ie);
                                }
                            }
                        }
                        catch (Exception E)
                        {
                            logger.Log(Logger.Levels.ERROR, "Error saving retrieving image: " + E.Message);
                        }

                        if (!config.GetAllImages)
                        {
                            counter++;
                        }
                    }
                }
            }
            int page = 1;
            TmdbSimilarMovies results = TMDB_API.GetSimilarMovies(id, page);
            while (results != null && results.results.Count != 0)
            {
                foreach (SimilarMovie movie in results.results)
                {
                    var sie = new SimilarItemEntity();
                    sie.TMDBID = movie.id;
                    TmdbMovie AdjMovie = TMDB_API.GetMovieInfo(movie.id);
                    sie.IMDBID = AdjMovie.imdb_id;

                    // Now try to get the Poster
                    string URL = baseImageURL + "/original" + movie.poster_path;
                    if (base.downloadImages)
                    {
                        Image image = null;
                        if (ImagesDownloaded.ContainsKey(URL))
                        {
                            var ie = new ImageEntity();
                            ie.URL = baseImageURL + movie.poster_path;
                            ie.Filename = ImagesDownloaded[URL].Filename;
                            ie.ImageSize = EImageSize.poster;
                            ie.ImageType = EImageType.poster;
                            sie.Poster = ie;
                            sie.Title = movie.title;
                            sie.Poster = ImagesDownloaded[URL];
                            returnValue.SimilarItems.Add(sie);
                        }
                        else
                        {
                            ImageEntity ie = new ImageEntity();
                            ie.URL = String.Format("{0}/original{1}", baseImageURL, movie.poster_path);
                            ie.ImageSize = EImageSize.poster;
                            ie.ImageType = EImageType.poster;

                            imageUpdateManager.GetUpdate(ie);

                            sie.Poster = ie;
                            sie.Title = movie.title;
                            returnValue.SimilarItems.Add(sie);
                        }
                    }
                }
                page++;
                results = TMDB_API.GetSimilarMovies(id, page);
            }

            imageUpdateManager.WaitForUpdates();

            logger.Log("Exiting TMDBProvider.GetMediaByID(" + id + ")");

            return returnValue;
        }

        public override MediaClass GetUpdateForMedia(MediaClass inputMedia, MediaMergeType MergeType)
        {
            throw new NotImplementedException();
        }

        public override VersionInfo GetVersionInfo()
        {
            VersionInfo verInfo;
            verInfo.Name = Assembly.GetExecutingAssembly().GetName().Name;
            verInfo.MajorVersion = Assembly.GetExecutingAssembly().GetName().Version.Major;
            verInfo.MinorVersion = Assembly.GetExecutingAssembly().GetName().Version.Minor;
            verInfo.BuildNumber = Assembly.GetExecutingAssembly().GetName().Version.Revision;
            return verInfo;
        }

        /// <summary>
        ///     Not applicable for a provider
        /// </summary>
        /// <returns> </returns>
        public override bool Run()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///     Search for Media by various media options:
        ///     IMDBID
        ///     TMDBID
        ///     Name
        /// </summary>
        /// <param name="mediaObject"> </param>
        /// <returns> </returns>
        public override List<MediaSearchReturn> SearchForMedia(MediaClass mediaObject)
        {
            logger.Log("Entering TMDBProvider.SearchForMediaByName(mediaObject)");
            if (mediaObject == null)
            {
                logger.Log(Logger.Levels.WARN, "mediaObject==null/empty, returning null");
                logger.Log("Exiting TMDBProvider.SearchForMediaByName(mediaObject), rc==null");
                return (null);
            }
            List<MediaSearchReturn> mediaList = new List<MediaSearchReturn>();

            // First check to see if one of the IDs we support is set, which for this provider is TMDBID and IMDBID
            if (!String.IsNullOrWhiteSpace(mediaObject.IMDBID))
            {
                logger.Log("Searching based on IMDBID");
                TmdbMovie movie = TMDB_API.GetMovieByIMDB(mediaObject.IMDBID, language);
                if (movie != null)
                {
                    MediaSearchReturn retVal = new MediaSearchReturn();
                    retVal.IMDBID = movie.imdb_id;
                    retVal.TMDBID = movie.id;
                    retVal.name = movie.title;
                    mediaList.Add(retVal);
                    logger.Log(String.Format("Found movie via IMDB ID: {0}", retVal.name));
                }
            }

            // Next TMDBID
            if (mediaObject.TmdbID > 0)
            {
                logger.Log("Searching based on TMDBID");
                var movie = GetMediaByID(mediaObject.TmdbID);
                if (movie != null)
                {
                    var retVal = new MediaSearchReturn();
                    retVal.IMDBID = movie.IMDBID;
                    retVal.TMDBID = movie.TmdbID;
                    retVal.name = movie.Title;
                    mediaList.Add(retVal);
                    logger.Log(String.Format("Found movie via TMDB ID: {0}", retVal.name));
                }
            }

            if (!String.IsNullOrWhiteSpace(mediaObject.Title))
            {
                List<MediaSearchReturn> nameSearch;
                nameSearch = mediaObject.Released != null
                                 ? SearchForMediaByNameAndYear(mediaObject.Title, mediaObject.Released.Value.Year)
                                 : SearchForMediaByName(mediaObject.Title);
                if (nameSearch != null)
                {
                    mediaList.AddRange(nameSearch);
                    nameSearch.Clear();
                }
            }

            // Our scoring is:
            //  100 = Same IMDB, TMDB or TVDB ID (And isnt null)
            //  Standard name/year scoring
            var returnValue = new List<MediaSearchReturn>();
            foreach (var msr in mediaList)
            {
                if (!String.IsNullOrWhiteSpace(msr.IMDBID) && msr.IMDBID.Equals(mediaObject.IMDBID))
                {
                    msr.pctLikelyMatch = 100;
                }
                if (msr.TMDBID != 0 && msr.TMDBID == mediaObject.TmdbID)
                {
                    msr.pctLikelyMatch = 100;
                }
                if (msr.TVDBID != 0 && msr.TVDBID == mediaObject.TvdbID)
                {
                    msr.pctLikelyMatch = 100;
                }
                returnValue.Add(msr);
            }

            // Now remove duplicates
            var tmp = new List<MediaSearchReturn>();
            foreach (var msr in returnValue)
            {
                bool dupe = false;
                foreach (var tmsr in tmp)
                {
                    if (tmsr.TMDBID == msr.TMDBID && tmsr.TMDBID != 0)
                    {
                        dupe = true;
                        break;
                    }
                    else
                    {
                        if (tmsr.IMDBID != null)
                        {
                            if (tmsr.IMDBID.Equals(msr.IMDBID))
                            {
                                dupe = true;
                                break;
                            }
                        }
                        if (tmsr.TVDBID == msr.TVDBID && tmsr.TVDBID != 0)
                        {
                            dupe = true;
                            break;
                        }
                    }
                }
                if (!dupe)
                {
                    tmp.Add(msr);
                }
            }
            tmp.Sort();
            tmp.Reverse();
            logger.Log("Exiting TMDBProvider.SearchForMediaByName(mediaObject), rc==" + tmp.Count);
            return tmp;
        }

        public override List<MediaSearchReturn> SearchForMedia(MediaClass mediaObject, int maxReturns)
        {
            logger.Log("Entering TMDBProvider.SearchForMediaByName(mediaObject, " + maxReturns + ")");
            var returnValue = SearchForMedia(mediaObject);
            while (returnValue.Count > maxReturns)
            {
                returnValue.RemoveAt(returnValue.Count);
            }
            logger.Log("Exiting TMDBProvider.SearchForMediaByName(mediaObject, " + maxReturns + "), rc==" +
                       returnValue.Count + " return values");
            return returnValue;
        }

        public override List<MediaSearchReturn> SearchForMediaByName(string name)
        {
            logger.Log("Entering TMDBProvider.SearchForMediaByName(" + name + ")");
            List<MediaSearchReturn> mediaList = SearchForMedia(name);

            // Set the score
            // Our score is 75 - EditDistance*2+10 if the name contains the name
            foreach (MediaSearchReturn msr in mediaList)
            {
                msr.pctLikelyMatch = 75 - (Strings.ComputeStringDistance(msr.name, name) * 2);
                if (msr.name.ToUpper().Contains(name.ToUpper()))
                {
                    msr.pctLikelyMatch += 10;
                }
                if (msr.pctLikelyMatch < 0)
                {
                    msr.pctLikelyMatch = 0;
                }
                if (msr.pctLikelyMatch > 100)
                {
                    msr.pctLikelyMatch = 100;
                }
            }

            mediaList.Sort();
            mediaList.Reverse();
            logger.Log(string.Format("Exiting TMDBProvider.SearchForMediaByName({0})", name));
            return mediaList;
        }

        public override List<MediaSearchReturn> SearchForMediaByName(string name, int maxReturns)
        {
            logger.Log(string.Format("Entering TMDBProvider.SearchForMediaByName({0},{1})", name, maxReturns));
            List<MediaSearchReturn> msr = SearchForMediaByName(name);
            while (msr.Count > maxReturns)
            {
                msr.RemoveAt(msr.Count);
            }

            logger.Log(string.Format("Exiting TMDBProvider.SearchForMediaByName({0},{1}), with {2} results", name,
                                     maxReturns, msr.Count));
            return msr;
        }

        public override List<MediaSearchReturn> SearchForMediaByNameAndYear(string name, int year)
        {
            logger.Log(string.Format("Entering TMDBProvider.SearchForMediaByNameAndYear({0},{1})", name, year));
            List<MediaSearchReturn> mediaList = SearchForMedia(name + " " + year);

            // Set the score
            // Our score is 75 - EditDistance*2+10 if the name contains the name+15-(Year Delta*2)
            foreach (MediaSearchReturn msr in mediaList)
            {
                msr.pctLikelyMatch = 75 - (Strings.ComputeStringDistance(msr.name, name) * 2) +
                                     (15 - (Math.Abs(msr.year - year) * 2));
                if (msr.name.ToUpper().Contains(name.ToUpper()))
                {
                    msr.pctLikelyMatch += 10;
                }
                if (msr.pctLikelyMatch < 0)
                {
                    msr.pctLikelyMatch = 0;
                }
                if (msr.pctLikelyMatch > 100)
                {
                    msr.pctLikelyMatch = 100;
                }
            }

            logger.Log(string.Format("Exiting TMDBProvider.SearchForMediaByNameAndYear({0},{1})", name, year));
            return mediaList;
        }

        private List<MediaSearchReturn> SearchForMedia(string query)
        {
            logger.Log("Entering TMDBProvider.SearchForMedia(" + query + ")");
            var msr = new List<MediaSearchReturn>();
            int page = 1;
            TmdbMovieSearch results = TMDB_API.SearchMovie(query, page);
            while (results != null && results.results.Count != 0)
            {
                foreach (MovieResult movie in results.results)
                {
                    var nMSR = new MediaSearchReturn();

                    nMSR.name = movie.title;
                    try
                    {
                        nMSR.year = DateTime.Parse(movie.release_date).Year;
                    }
                    catch (Exception)
                    {
                        nMSR.year = 0;
                    }
                    nMSR.TMDBID = movie.id;
                    TmdbMovie details = TMDB_API.GetMovieInfo(movie.id);
                    if (details != null)
                    {
                        nMSR.IMDBID = details.imdb_id;
                        nMSR.TMDBID = movie.id;
                        nMSR.TVDBID = 0;
                    }
                    msr.Add(nMSR);
                }
                page++;
                results = TMDB_API.SearchMovie(query, page);
            }

            logger.Log("Exiting SearchForMedia(" + query + ") with " + msr.Count + " entries");
            return (msr);
        }

        public override List<MediaSearchReturn> SearchForMediaByNameAndYear(string name, int year, int maxReturns)
        {
            logger.Log("Entering SearchForMediaByNameAndYear(" + name + "," + year + "," + maxReturns + ")");
            List<MediaSearchReturn> returnValue = SearchForMediaByNameAndYear(name, year);
            returnValue.Sort();
            returnValue.Reverse();
            if (returnValue.Count < maxReturns)
            {
                logger.Log("Entering SearchForMediaByNameAndYear(" + name + "," + year + "," + maxReturns + ") " +
                           returnValue.Count + " matches");
                return returnValue;
            }
            returnValue.RemoveRange(maxReturns, returnValue.Count - maxReturns);
            logger.Log("Entering SearchForMediaByNameAndYear(" + name + "," + year + "," + maxReturns + ") " +
                       returnValue.Count + " matches");

            return returnValue;
        }

        public override void SetDefaultConfig()
        {
            // Config Variables are:
            // Name - Language
            // Type - String
            // Provider ID - This guys ID
            // Description - The language you want to download movie info in (Default English)
            // Value - English

            logger.Log("Entering TMDBProvider.SetDefaultConfig()");
            VersionInfo vi = GetVersionInfo();
            base.pluginEntity.BuildNumber = vi.BuildNumber;
            base.pluginEntity.MajorVersion = vi.MajorVersion;
            base.pluginEntity.MinorVersion = vi.MinorVersion;
            base.pluginEntity.Name = vi.Name;
            base.pluginEntity.SaveOrUpdate();

            var ciH = new ConfigItemsHelper(config);

            ciH.CreateCIEntry(base.pluginEntity.ID, "Language", EValueType.STRING, "en",
                              "Language movie information will be downloaded in");
            logger.Log(
                String.Format("Set TMDBProvider Variable - Name: Language, type: string, value: en, ProviderID: {0}",
                              base.pluginEntity.ID));

            var Extensions = new string[17, 2]
                                 {
                                     {
                                         "AVI",
                                         "Common video container format.  AVI is the abbreviation for Audio Video Interleve format developed by Microsoft"
                                     },
                                     {"263", "H.263 encoded video file"},
                                     {"264", "H.264/MPEG-4 AVC video file"},
                                     {"bdmv", "Blu-ray information file"},
                                     {"divx", "DivX Media Format"},
                                     {"dvr-ms", "Microsoft Digital Video Recording"},
                                     {"m2t", "MPEG movie file"},
                                     {"m2ts", "MPEG-2 stream (Blu-Ray)"},
                                     {"m4v", "MPEG-4 video file format"},
                                     {"mkv", "Matroska video-audio multimedia file"},
                                     {"mov", "Apple QuickTime digital movie file"},
                                     {"mp4", "MPEG-4 video file format"},
                                     {"mpeg", "MPEG Movie"},
                                     {"mpg", "ProgDVB MPEG2 video file"},
                                     {"wmv", "Windows Media Video"},
                                     {"xvid", "XviD Codec"},
                                     {"wtv", "Windows Media Center recorded television file"}
                                 };
            if (base.pluginEntity.ExtensionsHandled == null)
            {
                base.pluginEntity.ExtensionsHandled = new List<MediaFileTypesEntity>();
            }

            for (int i = 0; i < Extensions.Length / 2; i++)
            {
                var tmp = new MediaFileTypesEntity();
                tmp.Description = Extensions[i, 1];
                tmp.Extension = Extensions[i, 0];
                tmp.SaveOrUpdate();
                base.pluginEntity.ExtensionsHandled.Add(tmp);
            }

            base.pluginEntity.SaveOrUpdate();
            logger.Log("Exiting TMDBProvider.SetDefaultConfig()");
        }

        #endregion Methods
    }
}